package com.ste.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Logger;

import com.ste.domain.Client;
import com.ste.domain.OrderBook;
import com.ste.domain.Stock;
import com.ste.server.command.Command;

public class Server {
	private final Integer QUEUE_CAPACITY = 100;

	private BlockingQueue<Command> messageQueue = new ArrayBlockingQueue<Command>(QUEUE_CAPACITY, true);
	private List<Client> clients = Collections.synchronizedList(new ArrayList<Client>());

	private Map<String, OrderBook> orderBooks = Collections.synchronizedMap(new HashMap<String, OrderBook>());

	private static Logger log = Logger.getLogger(Server.class.getName());

	private Server() {
		OrderBook orderBook = null;
		for (Stock stock : Stock.values()) {
			orderBook = new OrderBook(this);
			orderBooks.put(stock.name(), orderBook);
			new Thread(orderBook).start();
		}
	}

	private void listeningClients() {
		ServerSocket serverSocket = null;

		try {
			serverSocket = new ServerSocket(4444);
			while (true) {
				new Thread(new ClientHandler(serverSocket.accept(), this)).start();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				serverSocket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Server server = new Server();
		new Thread(new CommandHandler(server)).start();
		server.listeningClients();
	}

	public BlockingQueue<Command> getMessageQueue() {
		return messageQueue;
	}

	public boolean addClient(Client client) {
		log.info("Add Client");
		return clients.add(client);
	}

	public List<Client> getClients() {
		return clients;
	}

	public Map<String, OrderBook> getOrderBooks() {
		return orderBooks;
	}

	public void remove(Client client) {
		log.info("remove client");
		clients.remove(client);
	}
}
